Cardiovascular Dynamics: 12-to-8 Interval Analysis

b-splines
data-wrangle
ai-conversations
Author

Olgert Denas

Published

January 3, 2026

Wearing a heart rate monitor during exercise is great, but wearing it after the exercise is important too! HRR-60

This report analyzes heart rate variability and recovery during a treadmill session featuring intervals transitioning between 12 min/mile and 8 min/mile. By applying Bayesian B-Splines, I decompose the signal into continuous acceleration metrics and extract, as metrics of fitness:

The model

DRAFT

Data

Code
# Your current specific workout: 3 reps of (3m low, 1m high) + 2m cooldown
standard_3x4 = WorkoutConfig(phases=[
    WorkoutPhase(f"R1", 180, 'low'), WorkoutPhase(f"S1", 60, 'high'),
    WorkoutPhase(f"R2", 180, 'low'), WorkoutPhase(f"S2", 60, 'high'),
    WorkoutPhase(f"R3", 180, 'low'), WorkoutPhase(f"S3", 60, 'high'),
    WorkoutPhase("Cd", 120, 'cooldown')
])

file_paths = list(sorted(Path("polar_data").glob("*.CSV")))
report = TreadmillReport(standard_3x4, file_paths, False)
report.plot_raw_data()

Model validation

Code
fig, axes = plt.subplots(ncols=len(report.sessions), nrows=2, figsize=(14, 6), sharex=True, sharey='row')
report.plot_fit_accel(fig, axes)
/var/folders/kq/2zfcdcr577b47rsq8qxqmwjw0000gp/T/ipykernel_97982/991029321.py:146: FutureWarning: hdi currently interprets 2d data as (draw, shape) but this will change in a future release to (chain, draw) for coherence with other functions
  return cls(np.median(samples, axis=0), az.hdi(samples, hdi_prob=hdi_prob))
/var/folders/kq/2zfcdcr577b47rsq8qxqmwjw0000gp/T/ipykernel_97982/991029321.py:146: FutureWarning: hdi currently interprets 2d data as (draw, shape) but this will change in a future release to (chain, draw) for coherence with other functions
  return cls(np.median(samples, axis=0), az.hdi(samples, hdi_prob=hdi_prob))
/var/folders/kq/2zfcdcr577b47rsq8qxqmwjw0000gp/T/ipykernel_97982/991029321.py:146: FutureWarning: hdi currently interprets 2d data as (draw, shape) but this will change in a future release to (chain, draw) for coherence with other functions
  return cls(np.median(samples, axis=0), az.hdi(samples, hdi_prob=hdi_prob))
/var/folders/kq/2zfcdcr577b47rsq8qxqmwjw0000gp/T/ipykernel_97982/991029321.py:146: FutureWarning: hdi currently interprets 2d data as (draw, shape) but this will change in a future release to (chain, draw) for coherence with other functions
  return cls(np.median(samples, axis=0), az.hdi(samples, hdi_prob=hdi_prob))

Code
report = TreadmillReport(standard_3x4, file_paths, False)
fig, ax_quad = plt.subplots(1, 2, figsize=(10, 4), sharex=True, sharey=False)
report.plot_trend_vector(fig, ax_quad[0], 'ph')
report.plot_trend_vector(fig, ax_quad[1], 'pp')
ax_quad[1].axline((0, 0), slope=1, color='r', linestyle='--', label='$x=y$ line'); ax_quad[1].legend()

Code
report.plot_cardiac_cost()

Conclusion